<?php

/**
 * Description of ControlPage
 *
 * @author Ian Clarence <ian.clarence@gmail.com>
 */
abstract class ControlPage extends Component {
    
    /**
     * The output string to be displayed.
     * 
     * @var string
     */
    protected $rendered;
    
    /**
     * The 'pseudo file' of the current page.
     * 
     * @var string
     */
    protected $pseudoFile;
    
    /**
     * The URL idenfifier of the current page.
     * 
     * @var string
     */
    protected $urlIdentifier;
    
    /**
     * The Id of the article of the current page, if there is one.
     * 
     * @var integer
     */
    protected $articleId;
    
    /**
     * The page number of the current page, if pagination is being used.
     * 
     * @var integer
     */
    protected $pageNumber;
    
    /**
     * The view fields (template variables).
     * 
     * @var array
     */
    protected $viewFields = array();
    
    /**
     * The current page object.
     * 
     * @var Page
     */
    protected $page;

    /**
     * The constructor.
     */
    public function __construct() {
        $this->fields = Request::getVariable();
    }

    /**
     * Initial loading of the page.
     */
    protected function run() {
        $this->viewFields = $this->getPageViewFields();
        $this->viewFields['page_specific'] = $this->getViewFields();
        return $this->genPage();            
    }
    
    /**
     * Getting the 'pseudo-file' of the current page.
     * 
     * @return mixed
     */
    protected function getPageViewFields() {
        
        /**
         * Basic page parameters. 
         */
        $language = Utils::getLanguage();
        
        /**
         * Composing the APC key for the view fields. 
         */
        $apcKey = 'page';
        $apcKey .= $this->urlIdentifier ? '_' . $this->urlIdentifier : '';
        $apcKey .= '_subdomain_' . Utils::getSubdomain();
        $apcKey .= $language ? '_language_' . $language : '';
        $apcKey .= $this->articleId ? '_article_' . $this->articleId : '';
        $apcKey .= $this->pageNumber ? '_number_' . $this->pageNumber : '';
        
        /**
         * Callback parameters: the current page object. 
         */
        $params = array('page' => $this->page);

        /**
         * Retrieving the view fields, either from cache or from the database. 
         */        
        $callback = function($params) {
            return $params['page'] instanceof Page ? $params['page']->getViewFields() : FALSE;            
        };        
        $viewFields = Utils::apcCache($apcKey, $callback, STORE_PAGE_DATA_AS_CACHE == YES, $params);
        
        /**
         * Request parameters. 
         */
        $viewFields['request'] = $this->fields;
        
        /**
         * Browser information. 
         */
        $viewFields['browser'] = array();
        $browserParams = array('browser', 'version', 'platform');
        $browser = get_browser(NULL, TRUE);
        foreach ($browserParams as $browserParam) {
            $viewFields['browser'][$browserParam] = $browser[$browserParam];            
        }
        
        /**
         * Session Id. 
         */
        $session = System::getSession();
        $viewFields['session_id'] = $session->getId();
        
        /**
         * Server variables.
         */
        $viewFields['server_variables'] = $_SERVER;
        
        
        /**
         * Returning the view fields. 
         */
        return $viewFields;
    }
    
    /**
     * Getting the page-specific view fields.
     * 
     * @return array 
     */
    protected function getViewFields() {
        return array();
    }
    
    /**
     * Form submission.
     * 
     * @param string $action
     * @return bool
     */
    protected function process($action = NULL) {
        return FALSE;
    }
    
    /**
     * Generating an HTML page.
     * 
     * @return object
     */
    protected function genPageHtml() {
        $pageView = $this->genView(HTML_FILENAME, $this->viewFields);
        header('Content-type: text/html; charset=' . CHARSET);
        return $pageView;
    }
    
    /**
     * Generating a page using XSLT.
     * 
     * @return object
     */
    protected function genPageXslt() {
                        
        /**
         * @todo 
         * Go through the ViewXsl and XslView classes putting in XSL
         * so that the $viewFields parameter below is not needed.
         * Similarly for XML_PAGE_FILENAME. 
         */
        $pageView = $this->genView(XML_FILENAME, $this->viewFields);
        $pageView->useStylesheet();
        header('Content-type: text/xml; charset=' . CHARSET);
        return $pageView;
    }
    
    /**
     * Generating the page.
     * 
     * @return mixed
     */
    protected function genPage() {
        if (is_array($this->viewFields)) {
            switch ($this->pseudoFile) {
                case DEFAULT_FILENAME:
                    return USE_XSLT == YES ? $this->genPageXslt()->view() : $this->genPageHtml()->view();
                case HTML_FILENAME:
                    return $pageView = $this->genPageHtml()->view();
                case XML_PAGE_FILENAME:
                    $pageView = $this->genView($this->pseudoFile, $this->viewFields);
                    $pageView->useStylesheet();
                    header('Content-type: text/xml; charset=' . CHARSET);
                    return $pageView->view();
                case CSS_FILENAME:
                    $stylesheetView = $this->genView($this->pseudoFile, $this->viewFields);
                    header('Content-type: text/css; charset=' . CHARSET);
                    return $stylesheetView->view();
                case JAVASCRIPT_FILENAME:
                    $javaScriptView = $this->genView($this->pseudoFile, $this->viewFields);
                    header('Content-type: application/javascript; charset=' . CHARSET);
                    return $javaScriptView->view();
                case FEED_FILENAME:
                    $rssFeedView = $this->genView($this->pseudoFile, $this->viewFields);
                    header('Content-type: text/xml; charset=' . CHARSET);
                    return $rssFeedView->view();
                case XML_DATA_FILENAME:
                    $xmlDataView = $this->genView($this->pseudoFile, $this->viewFields);
                    header('Content-type: text/xml; charset=' . CHARSET);
                    return $xmlDataView->view();
                case XSL_FILENAME:
                    $xslView = $this->genView($this->pseudoFile, $this->viewFields);
                    header('Content-type: text/xml; charset=' . CHARSET);
                    return $xslView->view();
                case AJAX_FILENAME:
                    $ajaxView = $this->genView($this->pseudoFile, $this->viewFields);
                    $ajaxFunction = $this->getAction();
                    return $ajaxView->$ajaxFunction();
                case PROCESS_FILENAME:
                    $this->process($this->getAction());
                    return USE_XSLT == YES ? $this->genPageXslt()->view() : $this->genPageHtml()->view();
            }
        }
        else {
            return FALSE;
        }
    }
    
    /**
     * Generating the view object.
     *
     * @param string $pseudoFile
     * @param array $viewFields
     * @return mixed
     */
    protected function genView($pseudoFile, $viewFields = array()) {
        return NULL;
    }
    
    /**
     * Redirecting to a given URL.
     * 
     * @param string $urlIdentifier 
     */
    protected static function pageRedirect($urlIdentifier = NULL) {
        $page = Page::getPage($urlIdentifier);
        header('Location:' . $page->getFullUrl());
    }
    
    /**
     * Render the page.
     * 
     * @return string
     */
    public function render() {
        return $this->rendered;
    }
    
}